#ifndef DATA_FUNCTION_H_
#define DATA_FUNCTION_H_

/*头文件*/
#include <unistd.h>
#include <math.h>
#include "../Global_Define.h"
#include "../Global_Func/File/File_Deal.h"
#include "../Global_Func/MEM_Operation/MEM_Operation.h"
#include "../Global_Func/Port/Port.h"
#include "../Global_Func/LIST/List.h"

/*DATA部分相关宏定义*/
#define HIS_VALUE_NUM	3																				//< 存储历史值的数量
#define CARD_IO_MEMFAIL_DEAL(var)	{if ((var) == NULL) { FreeCARDIO(base); return LIST_MEMFAIL; }}		//< IO内存开辟失败释放
#define CLIST_PAR(name)	&(name##_List_Par)																//< 该类型卡件对应的链表私有参数结构体指针
#define CLIST_FUNC(name)		&(Card_List_Func[TYPE(name)])											//< 该类型卡件对应的链表私有函数结构体指针
#define CARD_WORK(name)	name##_WORK																		//< 卡件工作函数宏定义
#define CHANGE_CARD_LIST_PAR(name)	name##ChangeCardListPar												//< 修改该类型卡件属性
#define CHANGE_CARD_PAR(name)	name##ChangeCardPar														//< 卡件修改参数函数宏定义
#define INIT_CARD_STA(name)	name##InitCardSta															//< 初始化卡件不可调参数结构体宏定义

/*下位定义DATA卡件顺序表（顺序一定要注意）*/ 
typedef enum
{
	/*存放软点的卡件（此处将所有上位下发的软点都存放在这张模拟卡中，方便进行统一管理（该卡件只有一张）*/
	TYP_SAMAIO,								//< 软点卡件
	/*MODBUS系列通讯卡件*/
	TYP_MODBUS485_MASTER,					//< MODBUS-485通讯协议（做主站）
	TYP_MODBUS485_SLAVE,					//< MODBUS-485通讯协议（做从站）
	TYP_MODBUSTCP_MASTER,					//< MODBUS-TCP通讯协议（做主站）
	TYP_MODBUSTCP_SLAVE,					//< MODBUS-TCP通讯协议（做从站）

	/*104规约通讯*/
	TYP_IEC104TCP_SLAVE,					//< IEC104-TCP通讯协议 （做从站）
	TYP_IEC104TCP_MASTER,					//< IEC104-TCP通讯协议 （做主站）


	/*MOXA系列通讯卡件*/


	/*其他卡件*/
	TYP_LOAD_FORECAST,                        //<负荷预测卡件（Ftp协议，根据关键词区分）

	TYP_MAX_CARD,							//< 当前总卡件类型个数

}Card_Type_e;

/*模拟量滤波类型枚举*/
typedef enum {
	NO_FITER,								//< 不滤波
	MIDVALUE_FITER,							//< 中值滤波
	AVERAGE_FITER,							//<	平均滤波
	WEIGHTED_FITER,							//< 加权滤波
}Fiter_Mode_e;

/*卡件通道管理模式枚举量*/
typedef enum {
	TURN_TIMEOUT,							//< 切换状态为超时
	WRITE,									//< 写入采样值
	TURN_FORCE,								//< 切换状态为强制
	TURN_HOLD,								//< 切换状态为保持
	TURN_NORMAL,							//< 切换状态为正常（非强制、非保持）
	ALARM_SURE,								//< 进行报警确认操作
}Channel_OperaMode_e;

/*通道类型枚举量*/
typedef enum {
	NODEFINE = -1,
	DI_CHA,
	DO_CHA,
	AI_CHA,
	AO_CHA,
}Channel_type_e;

/*网卡选择*/
typedef enum {
	NETA,									//< 100网段
	NETB,									//< 101网段
}Net_Chosen_e;

/*串口选择*/
typedef enum {
	PORT0,									//< 0号串口
	PORT1,									//< 1号串口
}Port_Chosen_e;

/*数据点通讯网卡\串口工作状态枚举*/
typedef enum {
	UNCONNECT,								//< 未连接
	WORK,									//< 工作
	BAK,									//< 备用
}Device_State_e;

typedef enum {
	NOT_BCIO,								//< 不对IO硬点进行广播
	BCIO,									//< 广播IO硬点信息
	BCIO_AND_TIME,							//< 广播IO硬点信息及时间
}BcIO_Mode_e;

/*串口状态结构体*/
struct Port_State_t {
	Device_State_e Port0_State;				//< 串口0设备状态
	Device_State_e Port1_State;				//< 串口1设备状态
	char Port0_Fail_Count;					//< 串口0通讯失败计数
	char Port1_Fail_Count;					//< 串口1通讯失败计数
};

/*网段状态结构体*/
struct Net_State_t {
	Device_State_e NetA_State;				//< 0网段通讯状态
	Device_State_e NetB_State;				//< 1网段通讯状态
	char NetA_Fail_Count;					//< 0网段通讯失败计数
	char NetB_Fail_Count;					//< 1网段通讯失败计数
};

/*串口类通讯线程传入参数结构体*/
struct PortThread_Par_t {
	Port_Chosen_e Port_Chosen;				//< 串口选择情况
	const char* Port_Name;					//< 串口设备名称
	Port_State_t* pt;						//< 串口状态结构体指针
};

/*网口类通讯线程传入参数结构体*/
struct NetThread_Par_t {
	Net_Chosen_e Net_Chosen;				//< 网段选择情况
	char IP_Addr[IP_STR_LENGTH];			//< IP地址
	Net_State_t* pt;						//< 网段状态结构体指针
};

/*数字量、模拟量公有属性结构体*/
typedef struct {
	unsigned int ID;						//< 索引号
	long File_Read_Offset;					//< 数据点参数在数据库下装文件中的指针偏移量
	struct timespec LastReportTime;			//< 上次广播时间
	unsigned short Status;					//< 状态字
	unsigned short PreStatus;				//< 前一时刻状态字
	struct timespec AlarmTime;				//< 报警时间
	bool Is_BcFlg;							//< 是否进行广播标志（0-广播，1-不广播）
	bool Is_BcTimeFlg;						//< 是否广播时间标志（0-广播，1-不广播）
	bool IEC104_VaryFlg;					//< 数据点是否变化标志 (0-未变化，1-变化)
}DVAV_BASE_Property_t;

/*数字量可调属性结构体*/
typedef struct {
	bool InitValue;							//< 初始值
	int ExcMaxTime;							//< 广播IO例外报告最大时间间隔（ms）
	int ExcMinTime;							//< 广播IO例外报告最小时间间隔（ms）
	bool AlarmDef;							//< 报警定义（0-报警/1-报警）
	bool IsUse_Flg;							//< 是否启用标志
	bool Alarm_Ignore;						//< 是否屏蔽报警（0-不屏蔽/1-屏蔽）
}DV_PraProperty_t;

/*数字量静态属性结构体*/
typedef struct {
	bool CurOut_Value;						//< 当前输出值
	bool LastOut_Value;						//< 上一时刻输出值
	bool LastBC_Value;						//< 上一次广播值
}DV_StaProperty_t;

/*数字量信息结构体*/
typedef struct {
	DVAV_BASE_Property_t Base_Property;		//< 公有属性结构体
	DV_PraProperty_t Pra_Property;			//< 数字量可调属性结构体
	DV_StaProperty_t Sta_Property;			//< 数字量静态属性结构体
}DVChannel_t;

/*模拟量可调属性结构体*/
typedef struct {
	float InitValue;						//< 初始值
	float Phy_HLimit;						//< 物理量量程上限
	float Phy_LLimit;						//< 物理量量程下限
	float ExcDead;							//< 广播IO例外报告死区
	int ExcMaxTime;							//< 广播IO例外报告最大时间间隔（ms）
	int ExcMinTime;							//< 广播IO例外报告最小时间间隔（ms）
	float TinyValue;						//< 小信号切除值
	float Alarm_HLimit1;					//< 报警上限1
	float Alarm_LLimit1;					//< 报警下限1
	float Alarm_HLimit2;					//< 报警上限2
	float Alarm_LLimit2;					//< 报警下限2
	float Alarm_HLimit3;					//< 报警上限3
	float Alarm_LLimit3;					//< 报警下限3
	float AlarmDead;						//< 上下限报警死区
	float Alarm_Speed_Limit;				//< 速率报警限制
	/*float Alarm_Speed_Dead;*/				//< 速率报警死区			duan191210 应浙江电科院要求，添加
	float slope;							//< 斜率
	float intercept;						//< 截距
	Fiter_Mode_e FilterMode;				//< 滤波类型
	unsigned int AlarmIgnore;				//< 是否报警屏蔽
	bool IsUse_Flg;							//< 是否启用标志
}AV_PraProperty_t;

/*模拟量静态属性结构体*/
typedef struct {
	float CurOut_Value;						//< 当前最终输出值
	float LastSample_Value[HIS_VALUE_NUM];	//< 上几个时刻的采样值
	float LastOut_Value[HIS_VALUE_NUM];		//< 上几个时刻的最终输出值
	float LastBC_Value;						//< 上一次广播值
	struct timespec CurValue_Time;			//< 当前值产生时间
	struct timespec LastValue_Time;			//< 上一时刻值产生时间
}AV_StaProperty_t;

/*模拟量信息结构体*/
typedef struct {
	DVAV_BASE_Property_t Base_Property;		//< 公有属性结构体
	AV_PraProperty_t Pra_Property;			//< 模拟量可调属性结构体
	AV_StaProperty_t Sta_Property;			//< 模拟量静态属性结构体
}AVChannel_t;

/*卡件基本变量结构体*/
typedef struct
{
	List_Base_t List_Base;					//< 链表基本信息结构体
	unsigned char Status;					//< 状态字
	int Period_Count;						//< 基本运算周期轮询次数计数
	IO_Num_t IO_Num;						//< IO通道数量
	DVChannel_t* DIChannel;					//< 指向数字量输入通道信息的指针
	DVChannel_t* DOChannel;					//< 指向数字量输出通道信息的指针
	AVChannel_t* AIChannel;					//< 指向模拟量输入通道信息的指针
	AVChannel_t* AOChannel;					//< 指向模拟量输出通道信息的指针
	long Card_File_Read_Offset;				//< 卡件可调参数在数据库下装文件中的指针偏移量
}Card_Base_t;

/*模块所在链表私有函数结构体*/
typedef struct {
	void(*WORK_Func)();													//< 卡件运算函数（如无该功能，直接将该元素设置为NULL即可）
	int(*ChangeListPar)(Card_Base_t* arg, void** Data);					//< 修改该类型私有属性（如无该功能，直接将该元素设置为NULL即可）
	int(*ChangePar)(Card_Base_t* arg, void** Data);						//< 在线修改卡件参数函数（如无该功能，直接将该元素设置为NULL即可）
	int(*InitStaPar)(Card_Base_t* arg, void** Data);					//< 初始化卡件运算中间参数（如无该功能，直接将该元素设置为NULL即可）
}Card_List_Func_t;

/*DATA变量声明*/
extern List_Tab_t Card_List[TYP_MAX_CARD];	//< 声明存放卡件链表的结构体数组
extern int Card_TotalNum;					//< IO卡件总数量

/*DATA公共函数*/ 
void FreeCARDIO(Card_Base_t* base);																						//< CARD IO内存释放函数
List_Info_e AddCard(List_Tab_t* arg, unsigned int ID, IO_Num_t* IO_PinNum);												//< 增加卡件函数
List_Info_e DelCard(List_Tab_t* arg, unsigned int ID);																	//< 删除卡件函数
Channel_type_e Channel_Find(unsigned int ChannelID, void** Channel_pt);													//< 卡件通道检索
void BcTimeFlg_Set(DVAV_BASE_Property_t* base, BcIO_Mode_e BcIO_Mode);													//< 设置是否广播时间状态标志
void DV_Alarm(DVChannel_t* base);																						//< 数字量通道报警检测
void DV_Init(DVChannel_t* base);																						//< 数字量通道初始化程序
void DV_Write(DVChannel_t* base, bool value, Channel_OperaMode_e mode);													//< 数字量通道写入
void AV_Alarm(AVChannel_t* base);																						//< 模拟量通道报警检测
void AV_Init(AVChannel_t* base);																						//< 模拟量通道初始化程序
void AV_Write(AVChannel_t* base, float value, Channel_OperaMode_e mode);												//< 模拟量通道写入
int BCAVIO(AVChannel_t* base, void** Data, short* BCChannelNum);														//< 广播模拟量通道
int BCDVIO(DVChannel_t* base, void** Data, short* BCChannelNum);														//< 广播数字量通道
int ChangeChannelPar(void* Channel_pt, void** Data, Channel_type_e type);												//< 改变通道参数
int BakIO(void* base, void** Data, Channel_type_e type, short* BakChannelNum);											//< 备份IO硬点
bool Read_DATA_File();																									//< 读取DATA文件
void *tReadCard(void* arg);																								//< 读卡线程
List_Info_e SamaIOSetLink();																							//< 软点建立映射关系
void SamaIOGetModel(Card_Base_t* base, int i, unsigned int* Model_ID, unsigned int* Pt_ptr, Channel_type_e type);		//< 软点得出模块信息
void IP_Get(char* IP, unsigned char IP_Addr, Net_Chosen_e Net_Chosen);													//< IP地址获取


#endif